#include "stdafx.h"
#include "SDLRenderer.h"

#include "TransformComponent.h"
#include "SpriteComponent.h"
#include "AnimatedComponent.h"
#include "SDLTexture.h"
#include "SDLRenderable.h"
#include "Font.h"

using namespace std;

namespace ZeEngine
{
    SDLRenderer::SDLRenderer()
    {
    }

    SDLRenderer::~SDLRenderer()
    {
    }

	bool SDLRenderer::Init(const Vector2D<float>& screenResolution)
	{
		//Create the default viewport which is the full screen
		SDL_Rect viewport;
		viewport.x = 0;
		viewport.y = 0;
		viewport.w = static_cast<int>(screenResolution.GetX());
        viewport.h = static_cast<int>(screenResolution.GetY());
		m_viewports.push_back(viewport);

        return true;
	}

	void SDLRenderer::Render(SDL_Renderer& renderer, const TransformComponent& transformComponent, IRenderableComponent& renderable, float interpolation, const Vector2D<float>& cameraPosition, u32 viewPortID)
    {
        Vector2D<float> position = transformComponent.GetInterpolatedPosition(interpolation) - cameraPosition;
        float rotation = transformComponent.GetInterpolatedRotation(interpolation);

        m_renderables.push_back(SDLRenderable(&renderable, position, interpolation, rotation, viewPortID));
    }

	void SDLRenderer::RenderImpl(SDL_Renderer& renderer)
	{		
		SortRenderables();

		for each (SDLRenderable renderable in m_renderables)
		{
            SDL_RenderSetViewport(&renderer, &m_viewports[renderable.m_viewPortID]);
            renderable.Render(renderer);
		}

		SDL_RenderSetViewport(&renderer, &m_viewports[0]);

        ClearRenderables();
	}

	void SDLRenderer::SortRenderables()
	{
		//Sort by Z		
		sort(m_renderables.begin(), m_renderables.end(), [](const SDLRenderable& lhs, const SDLRenderable& rhs)
		{
			return lhs.m_pComponent->GetZ() < rhs.m_pComponent->GetZ();
		});
	}

	void SDLRenderer::ClearRenderables()
	{
		m_renderables.clear();
	}

	u32 SDLRenderer::AddViewport(const SDL_Rect& viewport)
	{
		m_viewports.push_back(viewport);

		return m_viewports.size() - 1;
	}

    SDL_Texture* SDLRenderer::CreateRenderedText(SDL_Renderer& renderer, Font* pFont, string text, SDL_Color textColor, u32 size)
    {          
        SDL_Texture* pReturnTexture = NULL;
  
        if (pFont)
        {
            TTF_Font* pTTFFont = pFont->GetFont(size);

            if (pFont)
            {
                //Render text surface
                SDL_Surface* textSurface = TTF_RenderText_Solid( pTTFFont, text.c_str(), textColor );

                if( textSurface == NULL )
                {
                    LOG_ERROR( "Unable to render text surface! SDL_ttf Error: " + string(TTF_GetError()) );
                }
                else
                {
                    //Create texture from surface pixels
                    pReturnTexture = SDL_CreateTextureFromSurface(&renderer, textSurface );
                    if( pReturnTexture == NULL )
                    {
                        LOG_ERROR( "Unable to create texture from rendered text! SDL Error: " +  string(SDL_GetError()) );
                    }

                    //Get rid of old surface
                    SDL_FreeSurface( textSurface );
                }          
            }
        }
        

        return pReturnTexture;
    }
}
